package com.cheng.example.geektime.javaconca.j05;


import java.util.ArrayList;
import java.util.List;

/**
 *  死锁需要同时满足四大条件
 *  1、互斥
 *  2、占用且等待
 *  3、不可抢占
 *  4、循环且等待
 */
public class Example05 {

}

//2、破坏占用且等待
class Allocator {
    private List<Object> als =
            new ArrayList<>();
    // 一次性申请所有资源
    synchronized boolean apply(
            Object from, Object to){
        if(als.contains(from) || als.contains(to)){
            return false;
        } else {
            als.add(from);
            als.add(to);
        }
        return true;
    }
    // 归还资源
    synchronized void free(
            Object from, Object to){
        als.remove(from);
        als.remove(to);
    }
}

class Account {
    // actr应该为单例
    private Allocator actr;
    private int balance;
    // 转账
    void transfer(Account target, int amt){
        // 一次性申请转出账户和转入账户，直到成功
        while(!actr.apply(this, target))
      ;
        try{
            // 锁定转出账户
            synchronized(this){
                // 锁定转入账户
                synchronized(target){
                    if (this.balance > amt){
                        this.balance -= amt;
                        target.balance += amt;
                    }
                }
            }
        } finally {
            actr.free(this, target);
        }
    }
}





//4、破坏循环且等待
//class Account {
//    private int id;
//    private int balance;
//
//    // 转账
//    void transfer(Account target, int amt) {
//        Account left = this;
//        Account right = target;
//        if (this.id > target.id) {
//            left = target;
//            right = this;
//        }
//        // 锁定序号小的账户
//        synchronized (left) {
//            // 锁定序号大的账户
//            synchronized (right) {
//                if (this.balance > amt) {
//                    this.balance -= amt;
//                    target.balance += amt;
//                }
//            }
//        }
//    }
//}